/**
 * @FilePath     : /src/lgmg_robots/agv_navigation/agv_navigate/include/agvNavigate/helpInc/node_event.h
 * @Description  : 定义了NavNodeEvent类，负责管理AGV事件的创建、更新和清空操作。 
 *                 使用互斥锁确保线程安全，提供了获取正常事件、更新事件、判断事件发生与否等功能。 
 * @Author       : xiujun.yang
 * @Version      : 1.0.0
 * @LastEditors  : haibo haibo.yang@lgmgim.cn
 * @LastEditTime : 2024-12-19 16:49:24
 * @Copyright (c) 2024 by 临工智能信息科技有限公司, All Rights Reserved. 
**/ 
#pragma once
#include "rclcpp/rclcpp.hpp"
#include "tools.h"
// 2023.12.20 modify byf haibo
#include <agv_msgs/msg/agv_event.hpp>
#include <agv_msgs/msg/agv_event_status.hpp>
#include <mutex>

// 当前节点的事件
class NavNodeEvent
{
public:
    /**
     * @brief 构造函数，初始化NavNodeEvent对象
     *
     * 调用Init函数进行初始化操作。
     */
    NavNodeEvent() {
        Init();
    }

    /**
     * @brief 清空事件队列
     *
     * 该函数使用互斥锁来保护对事件队列的访问，确保线程安全。
     * 它会清除send_event_队列中的所有元素。
     */
    void Clear() {
        std::lock_guard<std::mutex> locker(mutex_);
        send_event_.clear(); // 2023.12.19
    }

    /**
     * @brief 清空事件队列
     *
     * 使用互斥锁锁定，确保线程安全地清空事件队列。
     */
    std::vector<agv_msgs::msg::AGVEvent> GetEvent() {
        return send_event_;
    }

    /**
     * @brief 获取一个正常的AGV事件
     *
     * 创建一个新的AGV事件，设置其时间戳、序列号、框架ID、事件代码和描述信息，并返回该事件。
     *
     * @return 返回一个agv_msgs::msg::AGVEvent类型的对象，表示一个正常的AGV事件
     */
    agv_msgs::msg::AGVEvent GetNormalEvent() {
        agv_msgs::msg::AGVEvent event;
        rclcpp::Time timestamp = ROSTime();
        event.header.stamp = timestamp;
        event.header.frame_id = NodeName();
        event.ecode = agv_msgs::msg::AGVEvent::NONE_EVENT;
        event.description = "No Event";
        return event;
    }

    /**
     * @brief 更新一个事件
     *
     * 更新指定ID的事件信息，并将其发送给相关节点。
     *
     * @param id 事件ID
     * @param detail 事件详细信息
     * @param control_mode 控制模式
     * @param occur 事件是否发生
     */
    void UpdateOneEvent(int id, const std::string& detail, int control_mode, bool occur) { // 2023.12.20
        std::lock_guard<std::mutex> locker(mutex_);
        agv_msgs::msg::AGVEvent one_event;
        rclcpp::Time timestamp = ROSTime();
        one_event.header.stamp = timestamp;
        one_event.header.frame_id = NodeName();
        one_event.ecode = id;
        one_event.description = detail;
        one_event.action = control_mode;
        one_event.type = agv_msgs::msg::AGVEvent::ALARM;
        one_event.ackreq = true;
        one_event.eventtime = timestamp.seconds();
        SetNodeEvent(one_event, occur);
    }

    /**
     * @brief 判断事件是否发生
     *
     * 使用std::lock_guard锁定mutex_互斥锁，确保线程安全。
     * 如果send_event_队列不为空，则返回true；否则返回false。
     *
     * @return 如果send_event_队列不为空，则返回true；否则返回false。
     */
    bool Occur() {
        std::lock_guard<std::mutex> locker(mutex_);
        return !send_event_.empty();
    }

    /**
     * @brief 判断是否发生了紧急停止事件
     *
     * 使用互斥锁锁定保护，遍历发送事件列表，如果列表中存在紧急停止事件，则返回 true，否则返回 false。
     * 如果守护节点，曲线缓停，则不能直接获取此处急停状态
     * @return 如果发生紧急停止事件，则返回 true；否则返回 false。
     */
    bool EmgActionOccur() {
        std::lock_guard<std::mutex> locker(mutex_);
        for (const auto& event : send_event_) {
            if (event.action == agv_msgs::msg::AGVEvent::ESTOP) {
                return true;
            }
        }
        return false;
    }

private:
    /**
     * @brief 初始化函数
     *
     * 初始化函数，用于清空事件列表并重置序列号。
     */
    void Init() {
        // 首次需要清空事件列表
        // sendEvent.nodeId = AGV_NAV_NODE_ID;
        // sendEvent.nodeName = "agv_navigate_node";
        send_event_.clear();
        seq_ = 0;
    }

    /**
     * @brief 设置节点事件
     *
     * 根据事件编码和是否发生事件，更新或删除节点事件列表中的事件。
     *
     * @param single_event 单个事件信息
     * @param occur 事件是否发生（true表示发生，false表示未发生）
     *
     * @return 设置成功返回true，否则返回false
     */
    bool SetNodeEvent(const agv_msgs::msg::AGVEvent& single_event, bool occur) {
        bool ret = false;
        auto& event_list = send_event_;
        for (auto iter = event_list.begin(); iter != event_list.end(); ++iter) {
            if (iter->ecode == single_event.ecode) {
                if (!occur) {
                    // 删除事件
                    iter = event_list.erase(iter);
                } else {
                    *iter = single_event;
                    ret = true;
                }
                break;
            }
        }
        if (!ret && occur) {
            event_list.push_back(single_event);
            DEBUG_OUT("Insert a new singleEvent: occur_id:" << single_event.ecode
                                                             << ", occur:" << static_cast<int>(occur));
        }
        DEBUG_OUT("SetNodeEvent: id=" << single_event.ecode
                                       << ", details=" << single_event.description
                                       << ", occur:" << occur
                                       << ", control_mode=" << static_cast<int>(single_event.action));
        return ret;
    }
private:
    // 2023.12.19 modify by haibo
    std::vector<agv_msgs::msg::AGVEvent> send_event_; // 事件列表
    std::mutex mutex_;                           // 互斥锁
    int seq_;                                    // 事件序列号
};
